#include <stdio.h>
#include <string>
#include <iostream>

#include "Class2.h"
/*
function Test()
{
	this.x = 0;
	this.y = 0;
	this.sum = function()
	{
		return this.x + thix.y;
	}
}

var x = new Test;
x.sum();
*/
using namespace std;

#define set(v,member) int n = v.__proto__->member; if (n == 0) { n = v.__proto__->member = sizeof(v.m); } v.m[n]
#define get(v,member) v.m[v.__proto__->member]


struct Prototype;

struct var
{
	Prototype* __proto__;
	var* m;
	double n;
	string s;
	short t;
	
	//static void (var&) inc[3] = {&inc_num, &inc_object, &inc_string};

	var()
	{
	}
	
	var(double num)
	{
		n = num;
		t = 0;
	}
	
	var(Prototype* func)
	{
		__proto__ = func;
		t = 1;
	}
	
	var(string str)
	{
		s = str;
		t = 2;
	}
	
	
	void operator=(double num)
	{
		n = num;
		t = 0;
	}
	
	void operator=(Prototype* func)
	{
		__proto__ = func;
		t = 1;
	}
	
	void operator=(string& str)
	{
		s = str;
		t = 2;
	}
	
	void operator=(const var& func)
	{
		__proto__ = func.__proto__; m = func.m; n = func.n; s = func.s; t = func.t;
	}
	
	void operator++() { t == 0 ? ++n : void(0); }
	var operator+(double num) const { if (t == 0) return var(n + num); else return var(); }
	var operator+(const string& str) const { return var(toString() + str); }
	var operator+(const var& v) const { if ((t | v.t) == 0) return var(n + v.n); else return var(toString() + v.toString()); }
	
	bool operator<(double b) const { return n < b; }
	
	const string toString() const { return s; }
	/*
	var call(string member)()
	{
		return m[__traits(getMember, this.__proto__, member)].__proto__.call(this);
	}
	
	ref var get(string member)()
	{
		return m[__traits(getMember, this.__proto__, member)];
	}
	
	ref var opDispatch(string member)()
	{
		return m[__traits(getMember, this.__proto__, member)];
	}
	
	ref var set(const string member)()
	{
		int n = __traits(getMember, this.__proto__, member);
		if (n == 0)
		{
			m ~= var();
			n = __traits(getMember, this.__proto__, member) = m.length - 1;
		}
		return m[n];
	}
	*/
};

struct Prototype
{
	int x,y,sum,z;
	virtual var call(const var& _this) { return var(0.0);}
};

static void inc_num(var& v)
{ ++v.n; }

static void inc_object(var& v)
{ v.t = 0; v.n = 0; }

static void inc_string(var& v)
{ v.t = 0; v.n = atof(v.s.c_str()); ++v.n; }

static var add_num(var& v, double n)
{ return var(v.n + n); }

static var add_string(var& v, double n)
{ return var(v.s); }

static var add_object(var& v, double n)
{ return var(v.toString()); }

//static Prototype Null = new Prototype;


class Func : public Prototype
{
	var call(const var& _this)
	{
		return var(get(_this,x).n + get(_this,y).n);
	}
};

struct Test : public Prototype
{
	static var New()
	{
		var ret;
		ret.__proto__ = new Test();
		ret.m = new var[5];
		ret.__proto__->call(ret);
		return ret;
	}
	
	var call(const var& _this)
	{
		_this.m[y] = 1;
		_this.m[sum] = new Func();
		_this.m[x] = 2;
		return var(0.0);
	}
	
	Test()
	{
		x = 1; y = 2; sum = 3; z = 4;
	}
};



int main()
{
	Class1* x = new Class1();
	int y;
	/*Handle f = &Class1::_Virtual;
	for (unsigned i = 0; i < 1000000000; ++i)
	{
		Class1::_Virtual(x, &y);
	}*/

	Class2* cc = new Class2();

	reinterpret_cast<Class1*>(cc)->Virtual(&y);

	const long id = (long)x % MAX;
	for (unsigned i = 0; i < 1000000000; ++i)
	{
		Event::_all[id](x, &y);
	}

	for (unsigned i = 0; i < 1000000000; ++i)
	{
		x->Virtual(&y);
	}

	printf("%d",y);
	return 0;
}
